package tcards.android;

import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnTouchListener;

public class TcardTouchListener implements OnTouchListener {
	
	public interface TcardCommand {
		public void editCommand(TcardButton button);
		public void openCommand(TcardButton button);
		public void closeCommand(TcardButton button);
	}
	
	private static final String TAG = "TcardTouchListener";
	
	enum MoveState { 
		Down,
		TwoDown,
		Drag,
		Click
	}
	
	private MoveState mMoveState;
	private Point2D mStartPoint;
	private Point2D mStartPoint2;
	private Point2D mFirstEndPoint;
	
	private TcardCommand command;
	
	public TcardTouchListener(TcardCommand cmd) {
		command = cmd;
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		//dumpEvent(event);
		
		int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
		
		TcardButton button = (TcardButton) v.getParent().getParent();
		
		switch (actionCode) {
		case MotionEvent.ACTION_DOWN:
			mMoveState = MoveState.Down;
			mStartPoint = currentPoint(event);
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			mMoveState = MoveState.TwoDown;
			mStartPoint2 = currentPoint(event);
			break;
		case MotionEvent.ACTION_POINTER_UP:
			mFirstEndPoint = currentPoint(event);
			break;
		case MotionEvent.ACTION_UP:
			if(mMoveState == MoveState.Down) {
				float length = mStartPoint.length(currentPoint(event));
				if(length < 8)	{
					mMoveState = MoveState.Click;
					command.editCommand(button);
					return true;
				}
			} else if (mMoveState == MoveState.TwoDown) {
				float startLength = mStartPoint.length(mStartPoint2);
				float endLength = mFirstEndPoint.length(currentPoint(event));
				
				if(startLength > endLength)
					command.closeCommand(button);
				else
					command.openCommand(button);
				return true;
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if(mMoveState == MoveState.Down) {
				float length = mStartPoint.length(currentPoint(event));

				if(length > 12)
				{
					mMoveState = MoveState.Drag;
					v.startDrag(null, new DragShadowBuilder(button), button, 0);
					return true;
				}
			}
			break;
		}
		
		return false;
	}
	
	private Point2D currentPoint(MotionEvent event) {
		int pointer = event.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
		return 	new Point2D(event.getX(pointer), event.getY(pointer));
	}
	
	
	/** Show an event in the LogCat view, for debugging */
	@SuppressWarnings("unused")
	private void dumpEvent(MotionEvent event) {
	   String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
	      "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
	   StringBuilder sb = new StringBuilder();
	   int action = event.getAction();
	   int actionCode = action & MotionEvent.ACTION_MASK;
	   sb.append("event ACTION_" ).append(names[actionCode]);
	   if (actionCode == MotionEvent.ACTION_POINTER_DOWN
	         || actionCode == MotionEvent.ACTION_POINTER_UP) {
	      sb.append("(pid " ).append(
	      action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
	      sb.append(")" );
	   }
	   sb.append("[" );
	   for (int i = 0; i < event.getPointerCount(); i++) {
	      sb.append("#" ).append(i);
	      sb.append("(pid " ).append(event.getPointerId(i));
	      sb.append(")=" ).append((int) event.getX(i));
	      sb.append("," ).append((int) event.getY(i));
	      if (i + 1 < event.getPointerCount())
	         sb.append(";" );
	   }
	   sb.append("]" );
	   Log.d(TAG, sb.toString());
	}

}
